﻿package com.itita.ww2.core;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itita.ww2.game.alliance.AllianceManager;
import com.itita.ww2.game.user.UserService;
import com.itita.ww2.game.worldmap.WorldMapManager;
import com.itita.ww2.redis.core.Redis;
import com.itita.ww2.redis.core.RedisConfig;
import com.smartfoxserver.v2.db.SFSDBManager;
import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.util.TaskScheduler;
import com.itita.ww2.utils.MyBatisSessionUtil;
import com.itita.ww2.utils.channel.google.GoogleServerToken;
import com.itita.ww2.utils.properties.ServerProperties;

/**
 * 服务端数据管理器
 * @author NorthLan
 *
 */
public class ServerService {
	private static final Logger logger = LoggerFactory.getLogger(ServerService.class);

	private static ServerService instance;

	public static ServerService getInstance() {
		if (instance == null) {
			instance = new ServerService();
		}
		return instance;
	}

	private SFSExtension ext;
	private SFSDBManager dbManager;
	private TaskScheduler scheduler;
	// 
	private Redis redis;

	// Google
	private GoogleServerToken googleServerToken;

	public void init(SFSExtension ext, TaskScheduler scheduler) {
		this.ext = ext;
		this.dbManager = (SFSDBManager) ext.getParentZone().getDBManager();
		this.scheduler = scheduler;
		this.scheduler.resizeThreadPool(10); // default - 4
		MessageHandler.getInstance().init(this.ext); // 消息接口初始化
		MyBatisSessionUtil.getInstance().init(); // mybatis
		initRedis();
		initTimer();
		initGoogle();
		// 
		UserService.getInstance().init(); // 用户数据初始化
		AllianceManager.getInstance().init();
		WorldMapManager.getInstance().init();
	}

	/**
	 * 初始化redis
	 */
	private void initRedis() {
		// @formatter:off
		RedisConfig m_Config = new RedisConfig
				.Builder(ServerProperties.getString("redis.ip"), ServerProperties.getString("redis.password"), 
						ServerProperties.getInt("redis.port"))
				.setUpdateInterval(ServerProperties.getInt("redis.updateInterval"))
				.setPoolMaxAttr(ServerProperties.getInt("redis.pool.maxIdle"), ServerProperties.getInt("redis.pool.maxTotal"))
				.setPoolMaxWaitMillis(ServerProperties.getInt("redis.pool.maxWait"))
				.setPoolTest(ServerProperties.getBoolean("redis.pool.testOnBorrow"), ServerProperties.getBoolean("redis.pool.testOnReturn"))
				.setJmxEnable(ServerProperties.getBoolean("redis.pool.jmxEnable"))
				.setMysql(ServerProperties.getString("sm.db.driverName"),
						ServerProperties.getString("sm.db.url"),
						ServerProperties.getString("sm.db.username"),
						ServerProperties.getString("sm.db.password"))
				.setBatchCount(ServerProperties.getInt("redis.batchCount"))
				.build();
		// @formatter:on
		redis = new Redis(this.scheduler, m_Config);
		redis.flushAll();
	}

	/**
	 * 开始全局计时任务
	 */
	private void initTimer() {
		scheduler.scheduleAtFixedRate(new TaskPerSecond(), 0, 1, TimeUnit.SECONDS);
	}

	/**
	 * 初始化Google
	 * access_token
	 */
	private void initGoogle() {
		// @formatter:off
		googleServerToken = new GoogleServerToken
				.Builder(ServerProperties.getString("google_refresh_token"), 
						ServerProperties.getString("google_client_id"), 
						ServerProperties.getString("google_client_secret"))
				// .setExpiresIn(5)
				.build();
		// @formatter:on
		if (ServerProperties.getBoolean("proxy.enable")) {
			googleServerToken.getBuilder().setProxy(ServerProperties.getString("proxy.type"),
					ServerProperties.getString("proxy.ip"), ServerProperties.getInt("proxy.port"));
		}
		googleServerToken.start();
	}

	public Properties getConfigProperties() {
		Properties ret = null;
		if (this.ext != null) {
			ret = this.ext.getConfigProperties();
		} else {
			ret = new Properties();
			try {
				ret.load(new FileInputStream(getConfigFileName()));
			} catch (IOException e) {
				logger.error("read config properties error", e);
			}
		}
		return ret;
	}

	private String getConfigFileName() {
		String ret = "config.properties";
		if (this.ext != null) {
			ret = ext.getPropertiesFileName();
		}
		return ret;
	}

	public Optional<String> getConfigValue(String key, String defaultValue) {
		String ret = defaultValue;
		if (this.ext != null) {
			ret = this.ext.getConfigProperties().getProperty(key, defaultValue);
		}
		return Optional.ofNullable(ret);
	}

	public String getGoogleAccessToken() {
		return this.googleServerToken.getAccessToken();
	}

	public SFSExtension getMainExtension() {
		return this.ext;
	}

	public SFSDBManager getSFSDBManager() {
		return this.dbManager;
	}

	public final Redis getRedis() {
		return redis;
	}
}